@boostxyz/sdk 2.1.1 → 2.2.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.
Files changed (131) hide show
  1. package/dist/Actions/Action.cjs +1 -1
  2. package/dist/Actions/Action.cjs.map +1 -1
  3. package/dist/Actions/Action.d.ts +2 -1
  4. package/dist/Actions/Action.d.ts.map +1 -1
  5. package/dist/Actions/Action.js +14 -13
  6. package/dist/Actions/Action.js.map +1 -1
  7. package/dist/Actions/EventAction.cjs +1 -1
  8. package/dist/Actions/EventAction.cjs.map +1 -1
  9. package/dist/Actions/EventAction.d.ts.map +1 -1
  10. package/dist/Actions/EventAction.js +33 -33
  11. package/dist/Actions/EventAction.js.map +1 -1
  12. package/dist/AllowLists/AllowList.cjs +1 -1
  13. package/dist/AllowLists/AllowList.cjs.map +1 -1
  14. package/dist/AllowLists/AllowList.d.ts +2 -1
  15. package/dist/AllowLists/AllowList.d.ts.map +1 -1
  16. package/dist/AllowLists/AllowList.js +19 -18
  17. package/dist/AllowLists/AllowList.js.map +1 -1
  18. package/dist/AllowLists/SimpleAllowList.cjs +1 -1
  19. package/dist/AllowLists/SimpleAllowList.js +7 -7
  20. package/dist/AllowLists/SimpleDenyList.cjs +1 -1
  21. package/dist/AllowLists/SimpleDenyList.js +3 -3
  22. package/dist/Auth/PassthroughAuth.cjs +1 -1
  23. package/dist/Auth/PassthroughAuth.js +1 -1
  24. package/dist/BoostCore.cjs +2 -2
  25. package/dist/BoostCore.cjs.map +1 -1
  26. package/dist/BoostCore.d.ts +13 -4
  27. package/dist/BoostCore.d.ts.map +1 -1
  28. package/dist/BoostCore.js +58 -57
  29. package/dist/BoostCore.js.map +1 -1
  30. package/dist/BoostRegistry.cjs +1 -1
  31. package/dist/BoostRegistry.js +11 -11
  32. package/dist/{Budget-DpQgIZEx.js → Budget-B0q1S08L.js} +33 -32
  33. package/dist/{Budget-DpQgIZEx.js.map → Budget-B0q1S08L.js.map} +1 -1
  34. package/dist/{Budget-BxQMnsdx.cjs → Budget-BA_1sa1e.cjs} +2 -2
  35. package/dist/{Budget-BxQMnsdx.cjs.map → Budget-BA_1sa1e.cjs.map} +1 -1
  36. package/dist/Budgets/Budget.cjs +1 -1
  37. package/dist/Budgets/Budget.d.ts +2 -1
  38. package/dist/Budgets/Budget.d.ts.map +1 -1
  39. package/dist/Budgets/Budget.js +2 -2
  40. package/dist/Budgets/ManagedBudget.cjs +1 -1
  41. package/dist/Budgets/ManagedBudget.js +11 -11
  42. package/dist/Deployable/DeployableTarget.cjs +1 -1
  43. package/dist/Deployable/DeployableTarget.js +1 -1
  44. package/dist/Deployable/DeployableTargetWithRBAC.cjs +1 -1
  45. package/dist/Deployable/DeployableTargetWithRBAC.cjs.map +1 -1
  46. package/dist/Deployable/DeployableTargetWithRBAC.d.ts +158 -0
  47. package/dist/Deployable/DeployableTargetWithRBAC.d.ts.map +1 -1
  48. package/dist/Deployable/DeployableTargetWithRBAC.js +268 -31
  49. package/dist/Deployable/DeployableTargetWithRBAC.js.map +1 -1
  50. package/dist/Incentives/AllowListIncentive.cjs +1 -1
  51. package/dist/Incentives/AllowListIncentive.cjs.map +1 -1
  52. package/dist/Incentives/AllowListIncentive.js +27 -27
  53. package/dist/Incentives/AllowListIncentive.js.map +1 -1
  54. package/dist/Incentives/CGDAIncentive.cjs +1 -1
  55. package/dist/Incentives/CGDAIncentive.cjs.map +1 -1
  56. package/dist/Incentives/CGDAIncentive.js +9 -9
  57. package/dist/Incentives/CGDAIncentive.js.map +1 -1
  58. package/dist/Incentives/ERC20Incentive.cjs +1 -1
  59. package/dist/Incentives/ERC20Incentive.cjs.map +1 -1
  60. package/dist/Incentives/ERC20Incentive.js +30 -30
  61. package/dist/Incentives/ERC20Incentive.js.map +1 -1
  62. package/dist/Incentives/ERC20VariableCriteriaIncentive.cjs +1 -1
  63. package/dist/Incentives/ERC20VariableCriteriaIncentive.js +11 -11
  64. package/dist/Incentives/ERC20VariableIncentive.cjs +1 -1
  65. package/dist/Incentives/ERC20VariableIncentive.cjs.map +1 -1
  66. package/dist/Incentives/ERC20VariableIncentive.js +12 -12
  67. package/dist/Incentives/ERC20VariableIncentive.js.map +1 -1
  68. package/dist/Incentives/Incentive.cjs +1 -1
  69. package/dist/Incentives/Incentive.cjs.map +1 -1
  70. package/dist/Incentives/Incentive.d.ts +2 -1
  71. package/dist/Incentives/Incentive.d.ts.map +1 -1
  72. package/dist/Incentives/Incentive.js +29 -28
  73. package/dist/Incentives/Incentive.js.map +1 -1
  74. package/dist/Incentives/PointsIncentive.cjs +1 -1
  75. package/dist/Incentives/PointsIncentive.cjs.map +1 -1
  76. package/dist/Incentives/PointsIncentive.js +25 -25
  77. package/dist/Incentives/PointsIncentive.js.map +1 -1
  78. package/dist/{SimpleDenyList-CA24drhL.cjs → SimpleDenyList-DrQrJ14i.cjs} +2 -2
  79. package/dist/{SimpleDenyList-CA24drhL.cjs.map → SimpleDenyList-DrQrJ14i.cjs.map} +1 -1
  80. package/dist/{SimpleDenyList-UHgnaOb_.js → SimpleDenyList-DuCoaOlG.js} +9 -9
  81. package/dist/{SimpleDenyList-UHgnaOb_.js.map → SimpleDenyList-DuCoaOlG.js.map} +1 -1
  82. package/dist/Validators/LimitedSignerValidator.cjs +1 -1
  83. package/dist/Validators/LimitedSignerValidator.js +7 -7
  84. package/dist/Validators/SignerValidator.cjs +1 -1
  85. package/dist/Validators/SignerValidator.js +5 -5
  86. package/dist/Validators/Validator.cjs +1 -1
  87. package/dist/Validators/Validator.cjs.map +1 -1
  88. package/dist/Validators/Validator.d.ts +2 -1
  89. package/dist/Validators/Validator.d.ts.map +1 -1
  90. package/dist/Validators/Validator.js +22 -21
  91. package/dist/Validators/Validator.js.map +1 -1
  92. package/dist/deployments-BucJ-gwk.cjs +2 -0
  93. package/dist/deployments-BucJ-gwk.cjs.map +1 -0
  94. package/dist/deployments-CQu0bLhU.js +102 -0
  95. package/dist/deployments-CQu0bLhU.js.map +1 -0
  96. package/dist/deployments.json +77 -74
  97. package/dist/{generated-B0XfMfoq.js → generated-1ZT_mHJx.js} +673 -450
  98. package/dist/generated-1ZT_mHJx.js.map +1 -0
  99. package/dist/generated-CgBgbMNe.cjs +3 -0
  100. package/dist/generated-CgBgbMNe.cjs.map +1 -0
  101. package/dist/index.cjs +1 -1
  102. package/dist/index.js +3 -3
  103. package/package.json +2 -2
  104. package/src/Actions/Action.ts +3 -0
  105. package/src/Actions/EventAction.test.ts +49 -2
  106. package/src/Actions/EventAction.ts +12 -4
  107. package/src/AllowLists/AllowList.ts +3 -0
  108. package/src/BoostCore.ts +16 -11
  109. package/src/Budgets/Budget.ts +3 -0
  110. package/src/Deployable/DeployableTargetWithRBAC.test.ts +175 -0
  111. package/src/Deployable/DeployableTargetWithRBAC.ts +281 -0
  112. package/src/Incentives/AllowListIncentive.test.ts +48 -0
  113. package/src/Incentives/AllowListIncentive.ts +1 -1
  114. package/src/Incentives/CGDAIncentive.test.ts +50 -0
  115. package/src/Incentives/CGDAIncentive.ts +1 -1
  116. package/src/Incentives/ERC1155Incentive.ts +1 -1
  117. package/src/Incentives/ERC20Incentive.test.ts +49 -0
  118. package/src/Incentives/ERC20Incentive.ts +1 -1
  119. package/src/Incentives/ERC20VariableIncentive.test.ts +48 -0
  120. package/src/Incentives/ERC20VariableIncentive.ts +1 -1
  121. package/src/Incentives/Incentive.ts +3 -0
  122. package/src/Incentives/PointsIncentive.test.ts +51 -0
  123. package/src/Incentives/PointsIncentive.ts +1 -1
  124. package/src/Validators/Validator.ts +3 -0
  125. package/dist/deployments-BDumesUK.cjs +0 -2
  126. package/dist/deployments-BDumesUK.cjs.map +0 -1
  127. package/dist/deployments-DvYsMioW.js +0 -99
  128. package/dist/deployments-DvYsMioW.js.map +0 -1
  129. package/dist/generated-B0XfMfoq.js.map +0 -1
  130. package/dist/generated-pNKCp_Ez.cjs +0 -3
  131. package/dist/generated-pNKCp_Ez.cjs.map +0 -1
@@ -1,14 +1,27 @@
1
1
  import {
2
2
  rbacAbi,
3
+ readOwnableRolesOwnershipHandoverExpiresAt,
3
4
  readRbacHasAllRoles,
4
5
  readRbacHasAnyRole,
5
6
  readRbacIsAuthorized,
6
7
  readRbacRolesOf,
8
+ simulateOwnableRolesCancelOwnershipHandover,
9
+ simulateOwnableRolesCompleteOwnershipHandover,
10
+ simulateOwnableRolesRenounceOwnership,
11
+ simulateOwnableRolesRenounceRoles,
12
+ simulateOwnableRolesRequestOwnershipHandover,
13
+ simulateOwnableRolesTransferOwnership,
7
14
  simulateRbacGrantManyRoles,
8
15
  simulateRbacGrantRoles,
9
16
  simulateRbacRevokeManyRoles,
10
17
  simulateRbacRevokeRoles,
11
18
  simulateRbacSetAuthorized,
19
+ writeOwnableRolesCancelOwnershipHandover,
20
+ writeOwnableRolesCompleteOwnershipHandover,
21
+ writeOwnableRolesRenounceOwnership,
22
+ writeOwnableRolesRenounceRoles,
23
+ writeOwnableRolesRequestOwnershipHandover,
24
+ writeOwnableRolesTransferOwnership,
12
25
  writeRbacGrantManyRoles,
13
26
  writeRbacGrantRoles,
14
27
  writeRbacRevokeManyRoles,
@@ -426,4 +439,272 @@ export class DeployableTargetWithRBAC<
426
439
  ...(params as any),
427
440
  });
428
441
  }
442
+
443
+ /**
444
+ * Transfer ownership of the contract to a new address
445
+ *
446
+ * @public
447
+ * @async
448
+ * @param {Address} newOwner - The address to transfer ownership to
449
+ * @param {?WriteParams} [params]
450
+ * @returns {Promise<void>}
451
+ */
452
+ public async transferOwnership(newOwner: Address, params?: WriteParams) {
453
+ return await this.awaitResult(this.transferOwnershipRaw(newOwner, params));
454
+ }
455
+
456
+ /**
457
+ * Transfer ownership of the contract to a new address
458
+ *
459
+ * @public
460
+ * @async
461
+ * @param {Address} newOwner - The address to transfer ownership to
462
+ * @param {?WriteParams} [params]
463
+ * @returns {Promise<{ hash: `0x${string}`; result: void; }>}
464
+ */
465
+ public async transferOwnershipRaw(newOwner: Address, params?: WriteParams) {
466
+ const { request, result } = await simulateOwnableRolesTransferOwnership(
467
+ this._config,
468
+ {
469
+ address: this.assertValidAddress(),
470
+ args: [newOwner],
471
+ ...this.optionallyAttachAccount(),
472
+ // biome-ignore lint/suspicious/noExplicitAny: Accept any shape of valid wagmi/viem parameters, wagmi does the same thing internally
473
+ ...(params as any),
474
+ },
475
+ );
476
+ const hash = await writeOwnableRolesTransferOwnership(
477
+ this._config,
478
+ request,
479
+ );
480
+ return { hash, result };
481
+ }
482
+
483
+ /**
484
+ * Renounce ownership of the contract
485
+ *
486
+ * @public
487
+ * @async
488
+ * @param {?WriteParams} [params]
489
+ * @returns {Promise<void>}
490
+ */
491
+ public async renounceOwnership(params?: WriteParams) {
492
+ return await this.awaitResult(this.renounceOwnershipRaw(params));
493
+ }
494
+
495
+ /**
496
+ * Renounce ownership of the contract
497
+ *
498
+ * @public
499
+ * @async
500
+ * @param {?WriteParams} [params]
501
+ * @returns {Promise<{ hash: `0x${string}`; result: void; }>}
502
+ */
503
+ public async renounceOwnershipRaw(params?: WriteParams) {
504
+ const { request, result } = await simulateOwnableRolesRenounceOwnership(
505
+ this._config,
506
+ {
507
+ address: this.assertValidAddress(),
508
+ ...this.optionallyAttachAccount(),
509
+ // biome-ignore lint/suspicious/noExplicitAny: Accept any shape of valid wagmi/viem parameters, wagmi does the same thing internally
510
+ ...(params as any),
511
+ },
512
+ );
513
+ const hash = await writeOwnableRolesRenounceOwnership(
514
+ this._config,
515
+ request,
516
+ );
517
+ return { hash, result };
518
+ }
519
+
520
+ /**
521
+ * Request a two-step ownership handover to the caller
522
+ * The request will automatically expire in 48 hours
523
+ *
524
+ * Note: This is part of a two-step ownership transfer process:
525
+ * 1. New owner calls requestOwnershipHandover()
526
+ * 2. Current owner calls completeOwnershipHandover(newOwner)
527
+ *
528
+ * @public
529
+ * @async
530
+ * @param {?WriteParams} [params]
531
+ * @returns {Promise<void>}
532
+ */
533
+ public async requestOwnershipHandover(params?: WriteParams) {
534
+ return await this.awaitResult(this.requestOwnershipHandoverRaw(params));
535
+ }
536
+
537
+ /**
538
+ * Request a two-step ownership handover to the caller
539
+ * The request will automatically expire in 48 hours
540
+ *
541
+ * @public
542
+ * @async
543
+ * @param {?WriteParams} [params]
544
+ * @returns {Promise<{ hash: `0x${string}`; result: void; }>}
545
+ */
546
+ public async requestOwnershipHandoverRaw(params?: WriteParams) {
547
+ const { request, result } =
548
+ await simulateOwnableRolesRequestOwnershipHandover(this._config, {
549
+ address: this.assertValidAddress(),
550
+ ...this.optionallyAttachAccount(),
551
+ // biome-ignore lint/suspicious/noExplicitAny: Accept any shape of valid wagmi/viem parameters, wagmi does the same thing internally
552
+ ...(params as any),
553
+ });
554
+ const hash = await writeOwnableRolesRequestOwnershipHandover(
555
+ this._config,
556
+ request,
557
+ );
558
+ return { hash, result };
559
+ }
560
+
561
+ /**
562
+ * Complete a pending ownership handover to a new owner
563
+ * Must be called by the current owner after the new owner has requested the handover
564
+ *
565
+ * Note: This is part of a two-step ownership transfer process:
566
+ * 1. New owner calls requestOwnershipHandover()
567
+ * 2. Current owner calls completeOwnershipHandover(newOwner)
568
+ *
569
+ * @public
570
+ * @async
571
+ * @param {Address} pendingOwner - The address that requested the ownership handover
572
+ * @param {?WriteParams} [params]
573
+ * @returns {Promise<void>}
574
+ */
575
+ public async completeOwnershipHandover(
576
+ pendingOwner: Address,
577
+ params?: WriteParams,
578
+ ) {
579
+ return await this.awaitResult(
580
+ this.completeOwnershipHandoverRaw(pendingOwner, params),
581
+ );
582
+ }
583
+
584
+ /**
585
+ * Complete a pending ownership handover to a new owner
586
+ * Must be called by the current owner after the new owner has requested the handover
587
+ *
588
+ * @public
589
+ * @async
590
+ * @param {Address} pendingOwner - The address that requested the ownership handover
591
+ * @param {?WriteParams} [params]
592
+ * @returns {Promise<{ hash: `0x${string}`; result: void; }>}
593
+ */
594
+ public async completeOwnershipHandoverRaw(
595
+ pendingOwner: Address,
596
+ params?: WriteParams,
597
+ ) {
598
+ const { request, result } =
599
+ await simulateOwnableRolesCompleteOwnershipHandover(this._config, {
600
+ address: this.assertValidAddress(),
601
+ args: [pendingOwner],
602
+ ...this.optionallyAttachAccount(),
603
+ // biome-ignore lint/suspicious/noExplicitAny: Accept any shape of valid wagmi/viem parameters, wagmi does the same thing internally
604
+ ...(params as any),
605
+ });
606
+ const hash = await writeOwnableRolesCompleteOwnershipHandover(
607
+ this._config,
608
+ request,
609
+ );
610
+ return { hash, result };
611
+ }
612
+
613
+ /**
614
+ * Cancel a pending ownership handover request
615
+ * Must be called by the account that originally requested the handover
616
+ *
617
+ * @public
618
+ * @async
619
+ * @param {?WriteParams} [params]
620
+ * @returns {Promise<void>}
621
+ */
622
+ public async cancelOwnershipHandover(params?: WriteParams) {
623
+ return await this.awaitResult(this.cancelOwnershipHandoverRaw(params));
624
+ }
625
+
626
+ /**
627
+ * Cancel a pending ownership handover request
628
+ * Must be called by the account that originally requested the handover
629
+ *
630
+ * @public
631
+ * @async
632
+ * @param {?WriteParams} [params]
633
+ * @returns {Promise<{ hash: `0x${string}`; result: void; }>}
634
+ */
635
+ public async cancelOwnershipHandoverRaw(params?: WriteParams) {
636
+ const { request, result } =
637
+ await simulateOwnableRolesCancelOwnershipHandover(this._config, {
638
+ address: this.assertValidAddress(),
639
+ ...this.optionallyAttachAccount(),
640
+ // biome-ignore lint/suspicious/noExplicitAny: Accept any shape of valid wagmi/viem parameters, wagmi does the same thing internally
641
+ ...(params as any),
642
+ });
643
+ const hash = await writeOwnableRolesCancelOwnershipHandover(
644
+ this._config,
645
+ request,
646
+ );
647
+ return { hash, result };
648
+ }
649
+
650
+ /**
651
+ * Get the expiry timestamp for a pending ownership handover
652
+ * Returns 0 if there is no pending handover request for the given address
653
+ *
654
+ * @public
655
+ * @param {Address} pendingOwner - The address to check for pending handover requests
656
+ * @param {?ReadParams} [params]
657
+ * @returns {Promise<bigint>} - The timestamp when the handover request expires, or 0 if no request exists
658
+ */
659
+ public ownershipHandoverExpiresAt(
660
+ pendingOwner: Address,
661
+ params?: ReadParams,
662
+ ): Promise<bigint> {
663
+ return readOwnableRolesOwnershipHandoverExpiresAt(this._config, {
664
+ address: this.assertValidAddress(),
665
+ args: [pendingOwner],
666
+ ...this.optionallyAttachAccount(),
667
+ // biome-ignore lint/suspicious/noExplicitAny: Accept any shape of valid wagmi/viem parameters, wagmi does the same thing internally
668
+ ...(params as any),
669
+ });
670
+ }
671
+
672
+ /**
673
+ * Allow the caller to remove their own roles
674
+ * If the caller does not have a role, then it will be a no-op for that role
675
+ *
676
+ * @public
677
+ * @async
678
+ * @param {Roles} roles - Bitmap of roles to renounce
679
+ * @param {?WriteParams} [params]
680
+ * @returns {Promise<void>}
681
+ */
682
+ public async renounceRoles(roles: Roles, params?: WriteParams) {
683
+ return await this.awaitResult(this.renounceRolesRaw(roles, params));
684
+ }
685
+
686
+ /**
687
+ * Allow the caller to remove their own roles
688
+ * If the caller does not have a role, then it will be a no-op for that role
689
+ *
690
+ * @public
691
+ * @async
692
+ * @param {Roles} roles - Bitmap of roles to renounce
693
+ * @param {?WriteParams} [params]
694
+ * @returns {Promise<{ hash: `0x${string}`; result: void; }>}
695
+ */
696
+ public async renounceRolesRaw(roles: Roles, params?: WriteParams) {
697
+ const { request, result } = await simulateOwnableRolesRenounceRoles(
698
+ this._config,
699
+ {
700
+ address: this.assertValidAddress(),
701
+ args: [roles],
702
+ ...this.optionallyAttachAccount(),
703
+ // biome-ignore lint/suspicious/noExplicitAny: Accept any shape of valid wagmi/viem parameters, wagmi does the same thing internally
704
+ ...(params as any),
705
+ },
706
+ );
707
+ const hash = await writeOwnableRolesRenounceRoles(this._config, request);
708
+ return { hash, result };
709
+ }
429
710
  }
@@ -37,6 +37,7 @@ describe("AllowListIncentive", () => {
37
37
  reward: 1n,
38
38
  limit: 1n,
39
39
  });
40
+ // @ts-expect-error
40
41
  await action.deploy();
41
42
  expect(isAddress(action.assertValidAddress())).toBe(true);
42
43
  });
@@ -186,4 +187,51 @@ describe("AllowListIncentive", () => {
186
187
  expect(e).toBeInstanceOf(Error);
187
188
  }
188
189
  });
190
+
191
+ test("isClaimable returns expected values", async () => {
192
+ const referrer = accounts[1].account;
193
+ const trustedSigner = accounts[0];
194
+ const allowList = await loadFixture(freshAllowList(fixtures));
195
+ const allowListIncentive = new fixtures.bases.AllowListIncentive(
196
+ defaultOptions,
197
+ {
198
+ allowList: allowList.assertValidAddress(),
199
+ limit: 1n,
200
+ },
201
+ );
202
+ const boost = await freshBoost(fixtures, {
203
+ incentives: [allowListIncentive],
204
+ });
205
+ await allowList.grantManyRoles(
206
+ [allowListIncentive.assertValidAddress()],
207
+ [Roles.MANAGER],
208
+ );
209
+
210
+ const claimant = trustedSigner.account;
211
+ const incentiveData = allowListIncentive.buildClaimData();
212
+
213
+ // Should be claimable before claiming
214
+ expect(await boost.incentives[0]!.isClaimable({ target: claimant })).toBe(true);
215
+
216
+ const claimDataPayload = await boost.validator.encodeClaimData({
217
+ signer: trustedSigner,
218
+ incentiveData,
219
+ chainId: defaultOptions.config.chains[0].id,
220
+ incentiveQuantity: boost.incentives.length,
221
+ claimant,
222
+ boostId: boost.id,
223
+ });
224
+
225
+ // Claim the incentive
226
+ await fixtures.core.claimIncentive(
227
+ boost.id,
228
+ 0n,
229
+ referrer,
230
+ claimDataPayload,
231
+ { value: parseEther("0.000075"), account: trustedSigner.privateKey },
232
+ );
233
+
234
+ // Should not be claimable after claiming
235
+ expect(await boost.incentives[0]!.isClaimable({ target: claimant })).toBe(false);
236
+ });
189
237
  });
@@ -272,7 +272,7 @@ export class AllowListIncentive extends DeployableTarget<
272
272
  ) {
273
273
  return await readAllowListIncentiveIsClaimable(this._config, {
274
274
  address: this.assertValidAddress(),
275
- args: [prepareClaimPayload(payload)],
275
+ args: [payload.target, '0x'],
276
276
  // biome-ignore lint/suspicious/noExplicitAny: Accept any shape of valid wagmi/viem parameters, wagmi does the same thing internally
277
277
  ...(params as any),
278
278
  });
@@ -33,6 +33,7 @@ describe("CGDAIncentive", () => {
33
33
  rewardDecay: 1n,
34
34
  manager: budgets.budget.address || zeroAddress,
35
35
  });
36
+ // @ts-expect-error
36
37
  await action.deploy();
37
38
  expect(isAddress(action.assertValidAddress())).toBe(true);
38
39
  });
@@ -208,4 +209,53 @@ describe("CGDAIncentive", () => {
208
209
  true,
209
210
  );
210
211
  });
212
+
213
+ test("isClaimable returns expected values", async () => {
214
+ const referrer = accounts[1].account;
215
+ const trustedSigner = accounts[0];
216
+ const cgdaIncentive = fixtures.core.CGDAIncentive({
217
+ asset: budgets.erc20.assertValidAddress(),
218
+ initialReward: 1n,
219
+ totalBudget: 10n,
220
+ rewardBoost: 1n,
221
+ rewardDecay: 1n,
222
+ manager: budgets.budget.assertValidAddress(),
223
+ });
224
+ const boost = await freshBoost(fixtures, {
225
+ budget: budgets.budget,
226
+ incentives: [cgdaIncentive],
227
+ });
228
+
229
+ const claimant = trustedSigner.account;
230
+ const incentiveData = cgdaIncentive.buildClaimData();
231
+
232
+ // Should be claimable before claiming
233
+ expect(await boost.incentives[0]!.isClaimable({
234
+ target: claimant,
235
+ data: incentiveData
236
+ })).toBe(true);
237
+
238
+ const claimDataPayload = await boost.validator.encodeClaimData({
239
+ signer: trustedSigner,
240
+ incentiveData,
241
+ chainId: defaultOptions.config.chains[0].id,
242
+ incentiveQuantity: boost.incentives.length,
243
+ claimant,
244
+ boostId: boost.id,
245
+ });
246
+
247
+ // Claim the incentive
248
+ await fixtures.core.claimIncentive(
249
+ boost.id,
250
+ 0n,
251
+ referrer,
252
+ claimDataPayload,
253
+ );
254
+
255
+ // Should not be claimable after claiming
256
+ expect(await boost.incentives[0]!.isClaimable({
257
+ target: claimant,
258
+ data: incentiveData
259
+ })).toBe(false);
260
+ });
211
261
  });
@@ -375,7 +375,7 @@ export class CGDAIncentive extends DeployableTarget<
375
375
  public async isClaimable(payload: ClaimPayload, params?: ReadParams) {
376
376
  return await readCgdaIncentiveIsClaimable(this._config, {
377
377
  address: this.assertValidAddress(),
378
- args: [prepareClaimPayload(payload)],
378
+ args: [payload.target, payload.data],
379
379
  // biome-ignore lint/suspicious/noExplicitAny: Accept any shape of valid wagmi/viem parameters, wagmi does the same thing internally
380
380
  ...(params as any),
381
381
  });
@@ -359,7 +359,7 @@ export class ERC1155Incentive extends DeployableTarget<
359
359
  public async isClaimable(payload: ClaimPayload, params?: ReadParams) {
360
360
  return await readErc1155IncentiveIsClaimable(this._config, {
361
361
  address: this.assertValidAddress(),
362
- args: [prepareClaimPayload(payload)],
362
+ args: [payload.target, payload.data],
363
363
  // biome-ignore lint/suspicious/noExplicitAny: Accept any shape of valid wagmi/viem parameters, wagmi does the same thing internally
364
364
  ...(params as any),
365
365
  });
@@ -39,6 +39,7 @@ describe("ERC20Incentive", () => {
39
39
  limit: 1n,
40
40
  manager: zeroAddress,
41
41
  });
42
+ // @ts-expect-error
42
43
  await action.deploy();
43
44
  expect(isAddress(action.assertValidAddress())).toBe(true);
44
45
  });
@@ -205,4 +206,52 @@ describe("ERC20Incentive", () => {
205
206
  true,
206
207
  );
207
208
  });
209
+
210
+ test("isClaimable returns expected values", async () => {
211
+ const referrer = accounts[1].account;
212
+ const trustedSigner = accounts[0];
213
+ const erc20Incentive = fixtures.core.ERC20Incentive({
214
+ asset: budgets.erc20.assertValidAddress(),
215
+ strategy: StrategyType.POOL,
216
+ reward: 1n,
217
+ limit: 1n,
218
+ manager: budgets.budget.assertValidAddress(),
219
+ });
220
+ const boost = await freshBoost(fixtures, {
221
+ budget: budgets.budget,
222
+ incentives: [erc20Incentive],
223
+ });
224
+
225
+ const claimant = trustedSigner.account;
226
+ const incentiveData = erc20Incentive.buildClaimData();
227
+
228
+ // Should be claimable before claiming
229
+ expect(await boost.incentives[0]!.isClaimable({
230
+ target: claimant,
231
+ data: incentiveData
232
+ })).toBe(true);
233
+
234
+ const claimDataPayload = await boost.validator.encodeClaimData({
235
+ signer: trustedSigner,
236
+ incentiveData,
237
+ chainId: defaultOptions.config.chains[0].id,
238
+ incentiveQuantity: boost.incentives.length,
239
+ claimant,
240
+ boostId: boost.id,
241
+ });
242
+
243
+ // Claim the incentive
244
+ await fixtures.core.claimIncentive(
245
+ boost.id,
246
+ 0n,
247
+ referrer,
248
+ claimDataPayload,
249
+ );
250
+
251
+ // Should not be claimable after claiming
252
+ expect(await boost.incentives[0]!.isClaimable({
253
+ target: claimant,
254
+ data: incentiveData
255
+ })).toBe(false);
256
+ });
208
257
  });
@@ -373,7 +373,7 @@ export class ERC20Incentive extends DeployableTarget<
373
373
  public async isClaimable(payload: ClaimPayload, params?: ReadParams) {
374
374
  return await readErc20IncentiveIsClaimable(this._config, {
375
375
  address: this.assertValidAddress(),
376
- args: [prepareClaimPayload(payload)],
376
+ args: [payload.target, payload.data],
377
377
  // biome-ignore lint/suspicious/noExplicitAny: Accept any shape of valid wagmi/viem parameters, wagmi does the same thing internally
378
378
  ...(params as any),
379
379
  });
@@ -38,6 +38,7 @@ describe("ERC20VariableIncentive", () => {
38
38
  limit: 1n,
39
39
  manager: zeroAddress,
40
40
  });
41
+ // @ts-expect-error
41
42
  await action.deploy();
42
43
  expect(isAddress(action.assertValidAddress())).toBe(true);
43
44
  });
@@ -237,4 +238,51 @@ describe("ERC20VariableIncentive", () => {
237
238
  true,
238
239
  );
239
240
  });
241
+
242
+ test("isClaimable returns expected values", async () => {
243
+ const referrer = accounts[1].account;
244
+ const trustedSigner = accounts[0];
245
+ const erc20VariableIncentive = fixtures.core.ERC20VariableIncentive({
246
+ asset: budgets.erc20.assertValidAddress(),
247
+ reward: 1n,
248
+ limit: 1n,
249
+ manager: budgets.budget.assertValidAddress(),
250
+ });
251
+ const boost = await freshBoost(fixtures, {
252
+ budget: budgets.budget,
253
+ incentives: [erc20VariableIncentive],
254
+ });
255
+
256
+ const claimant = trustedSigner.account;
257
+ const incentiveData = erc20VariableIncentive.buildClaimData(parseEther("1"));
258
+
259
+ // Should be claimable before claiming
260
+ expect(await boost.incentives[0]!.isClaimable({
261
+ target: claimant,
262
+ data: incentiveData
263
+ })).toBe(true);
264
+
265
+ const claimDataPayload = await boost.validator.encodeClaimData({
266
+ signer: trustedSigner,
267
+ incentiveData,
268
+ chainId: defaultOptions.config.chains[0].id,
269
+ incentiveQuantity: boost.incentives.length,
270
+ claimant,
271
+ boostId: boost.id,
272
+ });
273
+
274
+ // Claim the incentive
275
+ await fixtures.core.claimIncentive(
276
+ boost.id,
277
+ 0n,
278
+ referrer,
279
+ claimDataPayload,
280
+ );
281
+
282
+ // Should not be claimable after claiming
283
+ expect(await boost.incentives[0]!.isClaimable({
284
+ target: claimant,
285
+ data: incentiveData
286
+ })).toBe(false);
287
+ });
240
288
  });
@@ -346,7 +346,7 @@ export class ERC20VariableIncentive<
346
346
  public async isClaimable(payload: ClaimPayload, params?: ReadParams) {
347
347
  return await readErc20VariableIncentiveIsClaimable(this._config, {
348
348
  address: this.assertValidAddress(),
349
- args: [prepareClaimPayload(payload)],
349
+ args: [payload.target, payload.data],
350
350
  // biome-ignore lint/suspicious/noExplicitAny: Accept any shape of valid wagmi/viem parameters, wagmi does the same thing internally
351
351
  ...(params as any),
352
352
  });
@@ -12,6 +12,7 @@ import { readContract } from '@wagmi/core';
12
12
  import type { Address, Hex } from 'viem';
13
13
  import type { DeployableOptions } from '../Deployable/Deployable';
14
14
  import { InvalidComponentInterfaceError } from '../errors';
15
+ import type { ReadParams } from '../utils';
15
16
  import { AllowListIncentive } from './AllowListIncentive';
16
17
  import { CGDAIncentive } from './CGDAIncentive';
17
18
  import { ERC20Incentive } from './ERC20Incentive';
@@ -73,11 +74,13 @@ export const IncentiveByComponentInterface = {
73
74
  export async function incentiveFromAddress(
74
75
  options: DeployableOptions,
75
76
  address: Address,
77
+ params?: ReadParams,
76
78
  ) {
77
79
  const interfaceId = (await readContract(options.config, {
78
80
  abi: aIncentiveAbi,
79
81
  functionName: 'getComponentInterface',
80
82
  address,
83
+ ...params,
81
84
  })) as keyof typeof IncentiveByComponentInterface;
82
85
  const Ctor = IncentiveByComponentInterface[interfaceId];
83
86
  if (!Ctor) {
@@ -32,6 +32,7 @@ describe("PointsIncentive", () => {
32
32
  reward: 1n,
33
33
  limit: 1n,
34
34
  });
35
+ // @ts-expect-error
35
36
  await action.deploy();
36
37
  expect(isAddress(action.assertValidAddress())).toBe(true);
37
38
  });
@@ -177,4 +178,54 @@ describe("PointsIncentive", () => {
177
178
  expect(e).toBeInstanceOf(Error);
178
179
  }
179
180
  });
181
+
182
+ test("isClaimable returns expected values", async () => {
183
+ const referrer = accounts[1].account;
184
+ const trustedSigner = accounts[0];
185
+ const pointsIncentive = fixtures.core.PointsIncentive({
186
+ venue: points.assertValidAddress(),
187
+ selector: bytes4("issue(address,uint256)"),
188
+ reward: 1n,
189
+ limit: 1n,
190
+ });
191
+ const boost = await freshBoost(fixtures, {
192
+ incentives: [pointsIncentive],
193
+ });
194
+
195
+ const claimant = trustedSigner.account;
196
+ const incentiveData = pointsIncentive.buildClaimData();
197
+
198
+ // Should be claimable before claiming
199
+ expect(await boost.incentives[0]!.isClaimable({
200
+ target: claimant,
201
+ data: incentiveData
202
+ })).toBe(true);
203
+
204
+ const claimDataPayload = await boost.validator.encodeClaimData({
205
+ signer: trustedSigner,
206
+ incentiveData,
207
+ chainId: defaultOptions.config.chains[0].id,
208
+ incentiveQuantity: boost.incentives.length,
209
+ claimant,
210
+ boostId: boost.id,
211
+ });
212
+
213
+ await writePointsGrantRoles(defaultOptions.config, {
214
+ address: points.assertValidAddress(),
215
+ args: [pointsIncentive.assertValidAddress(), 2n],
216
+ account: defaultOptions.account,
217
+ });
218
+ await fixtures.core.claimIncentive(
219
+ boost.id,
220
+ 0n,
221
+ referrer,
222
+ claimDataPayload,
223
+ );
224
+
225
+ // Should not be claimable after claiming
226
+ expect(await boost.incentives[0]!.isClaimable({
227
+ target: claimant,
228
+ data: incentiveData
229
+ })).toBe(false);
230
+ });
180
231
  });
@@ -290,7 +290,7 @@ export class PointsIncentive extends DeployableTarget<
290
290
  public async isClaimable(payload: ClaimPayload, params?: ReadParams) {
291
291
  return await readPointsIncentiveIsClaimable(this._config, {
292
292
  address: this.assertValidAddress(),
293
- args: [prepareClaimPayload(payload)],
293
+ args: [payload.target, payload.data],
294
294
  // biome-ignore lint/suspicious/noExplicitAny: Accept any shape of valid wagmi/viem parameters, wagmi does the same thing internally
295
295
  ...(params as any),
296
296
  });