@boostxyz/sdk 1.1.0-alpha.23 → 2.0.0-alpha.25

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 (134) hide show
  1. package/dist/Actions/Action.cjs +1 -1
  2. package/dist/Actions/Action.js +7 -7
  3. package/dist/Actions/EventAction.cjs +1 -1
  4. package/dist/Actions/EventAction.cjs.map +1 -1
  5. package/dist/Actions/EventAction.d.ts +32 -5
  6. package/dist/Actions/EventAction.d.ts.map +1 -1
  7. package/dist/Actions/EventAction.js +164 -137
  8. package/dist/Actions/EventAction.js.map +1 -1
  9. package/dist/AllowLists/AllowList.cjs +1 -1
  10. package/dist/AllowLists/AllowList.js +10 -10
  11. package/dist/AllowLists/SimpleAllowList.cjs +1 -1
  12. package/dist/AllowLists/SimpleAllowList.js +10 -10
  13. package/dist/AllowLists/SimpleDenyList.cjs +1 -1
  14. package/dist/AllowLists/SimpleDenyList.js +3 -3
  15. package/dist/Auth/PassthroughAuth.cjs +1 -1
  16. package/dist/Auth/PassthroughAuth.js +1 -1
  17. package/dist/BoostCore.cjs +2 -1
  18. package/dist/BoostCore.cjs.map +1 -1
  19. package/dist/BoostCore.d.ts +564 -1
  20. package/dist/BoostCore.d.ts.map +1 -1
  21. package/dist/BoostCore.js +1322 -29
  22. package/dist/BoostCore.js.map +1 -1
  23. package/dist/BoostRegistry.cjs +1 -1
  24. package/dist/BoostRegistry.js +27 -27
  25. package/dist/Budgets/Budget.cjs +1 -1
  26. package/dist/Budgets/Budget.js +2 -2
  27. package/dist/Budgets/ManagedBudget.cjs +1 -1
  28. package/dist/Budgets/ManagedBudget.js +23 -23
  29. package/dist/Deployable/DeployableTarget.cjs +1 -1
  30. package/dist/Deployable/DeployableTarget.js +1 -1
  31. package/dist/Deployable/DeployableTargetWithRBAC.cjs +1 -1
  32. package/dist/Deployable/DeployableTargetWithRBAC.js +23 -23
  33. package/dist/Incentives/AllowListIncentive.cjs +1 -1
  34. package/dist/Incentives/AllowListIncentive.js +8 -8
  35. package/dist/Incentives/CGDAIncentive.cjs +1 -1
  36. package/dist/Incentives/CGDAIncentive.js +12 -12
  37. package/dist/Incentives/ERC20Incentive.cjs +1 -1
  38. package/dist/Incentives/ERC20Incentive.js +16 -16
  39. package/dist/Incentives/ERC20VariableCriteriaIncentive.cjs +2 -0
  40. package/dist/Incentives/ERC20VariableCriteriaIncentive.cjs.map +1 -0
  41. package/dist/Incentives/ERC20VariableCriteriaIncentive.d.ts +42 -15
  42. package/dist/Incentives/ERC20VariableCriteriaIncentive.d.ts.map +1 -1
  43. package/dist/Incentives/ERC20VariableCriteriaIncentive.js +188 -0
  44. package/dist/Incentives/ERC20VariableCriteriaIncentive.js.map +1 -0
  45. package/dist/Incentives/ERC20VariableIncentive.cjs +2 -0
  46. package/dist/Incentives/ERC20VariableIncentive.cjs.map +1 -0
  47. package/dist/Incentives/ERC20VariableIncentive.d.ts +7 -5
  48. package/dist/Incentives/ERC20VariableIncentive.d.ts.map +1 -1
  49. package/dist/{Incentive-rM5nKznp.js → Incentives/ERC20VariableIncentive.js} +42 -67
  50. package/dist/Incentives/ERC20VariableIncentive.js.map +1 -0
  51. package/dist/Incentives/Incentive.cjs +1 -1
  52. package/dist/Incentives/Incentive.cjs.map +1 -1
  53. package/dist/Incentives/Incentive.d.ts +552 -3
  54. package/dist/Incentives/Incentive.d.ts.map +1 -1
  55. package/dist/Incentives/Incentive.js +40 -16
  56. package/dist/Incentives/Incentive.js.map +1 -1
  57. package/dist/Incentives/PointsIncentive.cjs +1 -1
  58. package/dist/Incentives/PointsIncentive.js +8 -8
  59. package/dist/{SimpleDenyList-DNj5qDWM.cjs → SimpleDenyList-BdlpZdDz.cjs} +2 -2
  60. package/dist/{SimpleDenyList-DNj5qDWM.cjs.map → SimpleDenyList-BdlpZdDz.cjs.map} +1 -1
  61. package/dist/{SimpleDenyList-BDXpY74P.js → SimpleDenyList-D0cyVUVv.js} +16 -16
  62. package/dist/{SimpleDenyList-BDXpY74P.js.map → SimpleDenyList-D0cyVUVv.js.map} +1 -1
  63. package/dist/Validators/LimitedSignerValidator.cjs +2 -0
  64. package/dist/Validators/LimitedSignerValidator.cjs.map +1 -0
  65. package/dist/Validators/LimitedSignerValidator.d.ts +806 -0
  66. package/dist/Validators/LimitedSignerValidator.d.ts.map +1 -0
  67. package/dist/Validators/LimitedSignerValidator.js +299 -0
  68. package/dist/Validators/LimitedSignerValidator.js.map +1 -0
  69. package/dist/Validators/SignerValidator.cjs +1 -1
  70. package/dist/Validators/SignerValidator.cjs.map +1 -1
  71. package/dist/Validators/SignerValidator.d.ts +2 -2
  72. package/dist/Validators/SignerValidator.js +5 -5
  73. package/dist/Validators/SignerValidator.js.map +1 -1
  74. package/dist/Validators/Validator.cjs +1 -1
  75. package/dist/Validators/Validator.cjs.map +1 -1
  76. package/dist/Validators/Validator.d.ts +22 -2
  77. package/dist/Validators/Validator.d.ts.map +1 -1
  78. package/dist/Validators/Validator.js +26 -17
  79. package/dist/Validators/Validator.js.map +1 -1
  80. package/dist/{componentInterfaces-BBCFkrZv.js → componentInterfaces-bIVo8eyA.js} +9 -9
  81. package/dist/componentInterfaces-bIVo8eyA.js.map +1 -0
  82. package/dist/{deployments-fJsWblwS.js → deployments-Ccx1MtoK.js} +5 -5
  83. package/dist/deployments-Ccx1MtoK.js.map +1 -0
  84. package/dist/{generated-CsNyWPKA.js → generated-BAKNSOjJ.js} +661 -381
  85. package/dist/generated-BAKNSOjJ.js.map +1 -0
  86. package/dist/generated-Cqn4wS01.cjs +3 -0
  87. package/dist/generated-Cqn4wS01.cjs.map +1 -0
  88. package/dist/index.cjs +1 -1
  89. package/dist/index.d.ts +1 -0
  90. package/dist/index.d.ts.map +1 -1
  91. package/dist/index.js +145 -132
  92. package/dist/index.js.map +1 -1
  93. package/dist/utils.cjs +1 -1
  94. package/dist/utils.cjs.map +1 -1
  95. package/dist/utils.d.ts +10 -0
  96. package/dist/utils.d.ts.map +1 -1
  97. package/dist/utils.js +27 -26
  98. package/dist/utils.js.map +1 -1
  99. package/package.json +21 -5
  100. package/src/Actions/EventAction.test.ts +381 -122
  101. package/src/Actions/EventAction.ts +85 -23
  102. package/src/BoostCore.test.ts +3 -3
  103. package/src/BoostCore.ts +51 -5
  104. package/src/Incentives/AllowListIncentive.test.ts +19 -21
  105. package/src/Incentives/CGDAIncentive.test.ts +20 -22
  106. package/src/Incentives/ERC1155Incentive.test.ts +14 -15
  107. package/src/Incentives/ERC20Incentive.test.ts +17 -19
  108. package/src/Incentives/ERC20VariableCriteriaIncentive.test.ts +62 -10
  109. package/src/Incentives/ERC20VariableCriteriaIncentive.ts +79 -37
  110. package/src/Incentives/ERC20VariableIncentive.test.ts +16 -18
  111. package/src/Incentives/ERC20VariableIncentive.ts +16 -8
  112. package/src/Incentives/Incentive.ts +4 -1
  113. package/src/Incentives/PointsIncentive.test.ts +3 -5
  114. package/src/Validators/LimitedSignerValidator.test.ts +223 -0
  115. package/src/Validators/LimitedSignerValidator.ts +707 -0
  116. package/src/Validators/SignerValidator.test.ts +21 -22
  117. package/src/Validators/SignerValidator.ts +2 -2
  118. package/src/Validators/Validator.test.ts +7 -1
  119. package/src/Validators/Validator.ts +30 -3
  120. package/src/index.test.ts +2 -0
  121. package/src/index.ts +1 -0
  122. package/src/utils.ts +11 -0
  123. package/dist/BoostCore-Btl5BdAs.cjs +0 -3
  124. package/dist/BoostCore-Btl5BdAs.cjs.map +0 -1
  125. package/dist/BoostCore-CD56zbYX.js +0 -2641
  126. package/dist/BoostCore-CD56zbYX.js.map +0 -1
  127. package/dist/Incentive-CcnOIc8L.cjs +0 -2
  128. package/dist/Incentive-CcnOIc8L.cjs.map +0 -1
  129. package/dist/Incentive-rM5nKznp.js.map +0 -1
  130. package/dist/componentInterfaces-BBCFkrZv.js.map +0 -1
  131. package/dist/deployments-fJsWblwS.js.map +0 -1
  132. package/dist/generated-CsNyWPKA.js.map +0 -1
  133. package/dist/generated-DHerxf1y.cjs +0 -3
  134. package/dist/generated-DHerxf1y.cjs.map +0 -1
@@ -25,6 +25,7 @@ import {
25
25
  fromHex,
26
26
  isAddress,
27
27
  isAddressEqual,
28
+ zeroAddress,
28
29
  zeroHash,
29
30
  } from 'viem';
30
31
  import { EventAction as EventActionBases } from '../../dist/deployments.json';
@@ -46,6 +47,7 @@ import {
46
47
  ValidationAbiMissingError,
47
48
  } from '../errors';
48
49
  import {
50
+ CheatCodes,
49
51
  type Overwrite,
50
52
  type ReadParams,
51
53
  RegistryType,
@@ -221,12 +223,13 @@ export interface ActionStep {
221
223
  * @property {AbiEvent | AbiFunction} [abiItem] - Optional ABI item definition.
222
224
  * @property {EventLogs} [logs] - Event logs to validate against. Required if 'hash' is not provided.
223
225
  * @property {Hex} [hash] - Transaction hash to validate against. Required if 'logs' is not provided.
224
- * @property {number} [chainId] - Chain ID for the transaction. Required if 'hash' is provided.
226
+ * @property {number} [chainId] - Chain ID for the transaction.
225
227
  */
226
228
  export type ValidateActionStepParams = {
227
229
  knownSignatures: Record<Hex, AbiEvent | AbiFunction>;
228
230
  abiItem?: AbiEvent | AbiFunction;
229
- } & ({ logs: EventLogs } | { hash: Hex; chainId: number });
231
+ chainId: number;
232
+ } & ({ logs: EventLogs } | { hash: Hex });
230
233
 
231
234
  /**
232
235
  * You can either supply a simplified version of the payload, or one that explicitly declares action steps.
@@ -482,6 +485,8 @@ export class EventAction extends DeployableTarget<
482
485
  /**
483
486
  * Derives the action claimant address from a transaction based on the provided ActionClaimant configuration.
484
487
  * This method supports both event-based and function-based claimant derivation.
488
+ * **Important**: The claimant is considered to be `transaction.from` when `claimant.fieldIndex` is 255 using CheatCodes enum.
489
+ * This may have unintended side effects for bridged transactions and SCW transactions, so these are considered unsupported use cases for the time being.
485
490
  *
486
491
  ** @example
487
492
  * // Example usage
@@ -515,7 +520,32 @@ export class EventAction extends DeployableTarget<
515
520
  claimant: ActionClaimant,
516
521
  params: ValidateActionStepParams,
517
522
  ): Promise<Address | undefined> {
523
+ // find message sender and return it
524
+ // WARNING: this is error prone in bridged transactions and SCW transactions, as this will return exit node
525
+ if (claimant.fieldIndex === CheatCodes.TX_SENDER_CLAIMANT) {
526
+ if ('hash' in params) {
527
+ const transaction = await getTransaction(this._config, {
528
+ hash: params.hash,
529
+ chainId: params.chainId,
530
+ });
531
+ return transaction.from;
532
+ }
533
+ if ('logs' in params) {
534
+ for (let log of params.logs) {
535
+ if (log.transactionHash) {
536
+ const transaction = await getTransaction(this._config, {
537
+ hash: log.transactionHash,
538
+ chainId: claimant.chainid,
539
+ });
540
+ return transaction.from;
541
+ }
542
+ }
543
+ }
544
+ return undefined;
545
+ }
546
+
518
547
  const signature = claimant.signature;
548
+
519
549
  if (claimant.signatureType === SignatureType.EVENT) {
520
550
  let event: AbiEvent;
521
551
  if (params.abiItem) event = params.abiItem as AbiEvent;
@@ -556,13 +586,10 @@ export class EventAction extends DeployableTarget<
556
586
  }
557
587
  return address;
558
588
  }
559
- if (
560
- claimant.signatureType === SignatureType.FUNC &&
561
- 'hash' in params &&
562
- 'chainId' in params
563
- ) {
589
+ if (claimant.signatureType === SignatureType.FUNC && 'hash' in params) {
564
590
  const transaction = await getTransaction(this._config, {
565
591
  hash: params.hash,
592
+ chainId: params.chainId,
566
593
  });
567
594
  if (!isAddressEqual(transaction.to!, claimant.targetContract)) return;
568
595
  let func: AbiFunction;
@@ -672,11 +699,9 @@ export class EventAction extends DeployableTarget<
672
699
  return this.isActionEventValid(actionStep, params.logs);
673
700
  }
674
701
 
675
- const client = this._config.getClient({
676
- chainId: params.chainId,
677
- }) as PublicClient;
678
- const receipt = await client.getTransactionReceipt({
702
+ const receipt = await getTransactionReceipt(this._config, {
679
703
  hash: params.hash,
704
+ chainId: params.chainId,
680
705
  });
681
706
  const decodedLogs = receipt.logs.map((log) => {
682
707
  const { eventName, args } = decodeEventLog({
@@ -692,11 +717,9 @@ export class EventAction extends DeployableTarget<
692
717
  }
693
718
  if (actionStep.signatureType === SignatureType.FUNC) {
694
719
  if ('hash' in params && 'chainId' in params) {
695
- const client = this._config.getClient({
696
- chainId: params.chainId,
697
- }) as PublicClient;
698
- const transaction = await client.getTransaction({
720
+ const transaction = await getTransaction(this._config, {
699
721
  hash: params.hash,
722
+ chainId: params.chainId,
700
723
  });
701
724
  return this.isActionFunctionValid(actionStep, transaction, params);
702
725
  }
@@ -802,7 +825,7 @@ export class EventAction extends DeployableTarget<
802
825
  if (
803
826
  criteria.filterType === FilterType.EQUAL &&
804
827
  criteria.fieldType === PrimitiveType.BYTES &&
805
- criteria.fieldIndex === 255
828
+ criteria.fieldIndex === CheatCodes.ANY_ACTION_PARAM
806
829
  ) {
807
830
  return true;
808
831
  }
@@ -906,7 +929,7 @@ export class EventAction extends DeployableTarget<
906
929
 
907
930
  /**
908
931
  * Validates a {@link Log} against a given criteria.
909
- * If the criteria's fieldIndex is 255, it is reserved for anyValidation
932
+ * If the criteria's fieldIndex is 255 (using CheatCodes enum), it is reserved for anyValidation
910
933
  *
911
934
  * @param {Criteria} criteria - The criteria to validate against.
912
935
  * @param {Log} log - The Viem event log.
@@ -918,7 +941,8 @@ export class EventAction extends DeployableTarget<
918
941
  ): boolean {
919
942
  if (
920
943
  !Array.isArray(log.args) ||
921
- (log.args.length <= criteria.fieldIndex && criteria.fieldIndex !== 255)
944
+ (log.args.length <= criteria.fieldIndex &&
945
+ criteria.fieldIndex !== CheatCodes.ANY_ACTION_PARAM)
922
946
  ) {
923
947
  throw new DecodedArgsMalformedError({
924
948
  log,
@@ -928,7 +952,9 @@ export class EventAction extends DeployableTarget<
928
952
  }
929
953
 
930
954
  const fieldValue =
931
- criteria.fieldIndex === 255 ? zeroHash : log.args.at(criteria.fieldIndex);
955
+ criteria.fieldIndex === CheatCodes.ANY_ACTION_PARAM
956
+ ? zeroHash
957
+ : log.args.at(criteria.fieldIndex);
932
958
 
933
959
  if (fieldValue === undefined) {
934
960
  throw new FieldValueUndefinedError({ log, criteria, fieldValue });
@@ -938,7 +964,7 @@ export class EventAction extends DeployableTarget<
938
964
 
939
965
  /**
940
966
  * Validates a function's decoded arguments against a given criteria.
941
- * If the criteria's fieldIndex is 255, it is reserved for anyValidation
967
+ * If the criteria's fieldIndex is 255 (using CheatCodes enum), it is reserved for anyValidation
942
968
  *
943
969
  * @param {Criteria} criteria - The criteria to validate against.
944
970
  * @param {unknown[]} decodedArgs - The decoded arguments of the function call.
@@ -949,7 +975,9 @@ export class EventAction extends DeployableTarget<
949
975
  decodedArgs: readonly (string | bigint)[],
950
976
  ): boolean {
951
977
  const fieldValue =
952
- criteria.fieldIndex === 255 ? zeroHash : decodedArgs[criteria.fieldIndex];
978
+ criteria.fieldIndex === CheatCodes.ANY_ACTION_PARAM
979
+ ? zeroHash
980
+ : decodedArgs[criteria.fieldIndex];
953
981
  if (fieldValue === undefined) {
954
982
  throw new FieldValueUndefinedError({
955
983
  criteria,
@@ -1221,7 +1249,7 @@ export function prepareEventActionPayload({
1221
1249
  * This function returns a Criteria object with the following properties:
1222
1250
  * - filterType: Set to EQUAL for exact matching
1223
1251
  * - fieldType: Set to BYTES to handle any data type
1224
- * - fieldIndex: Set to 255, which is typically used to indicate "any" or "all" in this context
1252
+ * - fieldIndex: Set to 255, which is typically used to indicate "any" or "all" in this context using CheatCodes enum
1225
1253
  * - filterData: Set to zeroHash (0x0000...0000)
1226
1254
  *
1227
1255
  * @returns {Criteria} A Criteria object that can be used to match any action parameter
@@ -1238,7 +1266,41 @@ export function anyActionParameter(): Criteria {
1238
1266
  return {
1239
1267
  filterType: FilterType.EQUAL,
1240
1268
  fieldType: PrimitiveType.BYTES,
1241
- fieldIndex: 255,
1269
+ fieldIndex: CheatCodes.ANY_ACTION_PARAM,
1242
1270
  filterData: zeroHash,
1243
1271
  };
1244
1272
  }
1273
+
1274
+ /**
1275
+ * Creates an ActionClaimant object that represents the transaction sender as the claimant.
1276
+ * This function is useful when you want to set up an action where the transaction sender is always considered the valid claimant,
1277
+ * regardless of the event or function parameters.
1278
+ *
1279
+ * The returned ActionClaimant has the following properties:
1280
+ * - signatureType: Set to SignatureType.EVENT (though it doesn't matter for this case)
1281
+ * - signature: Set to zeroHash (0x0000...0000)
1282
+ * - fieldIndex: Set to 255, indicating "any" field using CheatCodes enum
1283
+ * - targetContract: Set to zeroAddress (0x0000...0000)
1284
+ * - chainid: Set to 0, indicating it's valid for any chain
1285
+ *
1286
+ * @returns {ActionClaimant} An ActionClaimant object representing the msg.sender
1287
+ *
1288
+ * @example
1289
+ * const eventAction = new EventAction();
1290
+ * const payload: EventActionPayload = {
1291
+ * actionClaimant: transactionSenderClaimant(),
1292
+ * actionSteps: [
1293
+ * // ... define your action steps here
1294
+ * ]
1295
+ * };
1296
+ * await eventAction.deploy(payload);
1297
+ */
1298
+ export function transactionSenderClaimant(): ActionClaimant {
1299
+ return {
1300
+ signatureType: SignatureType.EVENT,
1301
+ signature: zeroHash,
1302
+ fieldIndex: CheatCodes.TX_SENDER_CLAIMANT,
1303
+ targetContract: zeroAddress,
1304
+ chainid: 0,
1305
+ };
1306
+ }
@@ -17,6 +17,7 @@ import type { ERC20Incentive } from "./Incentives/ERC20Incentive";
17
17
  import { StrategyType } from "./claiming";
18
18
  import { BoostNotFoundError, IncentiveNotCloneableError } from "./errors";
19
19
  import { bytes4 } from "./utils";
20
+ import { BoostValidatorEOA } from "./Validators/Validator";
20
21
 
21
22
  let fixtures: Fixtures, budgets: BudgetFixtures;
22
23
 
@@ -843,7 +844,7 @@ describe("BoostCore", () => {
843
844
  expect(validator.payload?.validatorCaller).toBe(core.assertValidAddress());
844
845
 
845
846
  // expect current account to be a signer
846
- const signer = await validator.signers(defaultOptions.account.address);
847
+ const signer = await validator.signers(BoostValidatorEOA.TESTNET);
847
848
  expect(signer).toBeDefined();
848
849
  expect(signer).toBe(true);
849
850
  });
@@ -867,12 +868,11 @@ describe("BoostCore", () => {
867
868
 
868
869
  const claimant = trustedSigner.account;
869
870
  const incentiveData = pad("0xdef456232173821931823712381232131391321934");
870
- const incentiveQuantity = 1;
871
871
  const claimDataPayload = await boost.validator.encodeClaimData({
872
872
  signer: trustedSigner,
873
873
  incentiveData,
874
874
  chainId: defaultOptions.config.chains[0].id,
875
- incentiveQuantity,
875
+ incentiveQuantity: boost.incentives.length,
876
876
  claimant,
877
877
  boostId: boost.id,
878
878
  });
package/src/BoostCore.ts CHANGED
@@ -21,6 +21,7 @@ import { bytecode } from '@boostxyz/evm/artifacts/contracts/BoostCore.sol/BoostC
21
21
  import {
22
22
  type GetTransactionReceiptParameters,
23
23
  getAccount,
24
+ getChains,
24
25
  getTransactionReceipt,
25
26
  waitForTransactionReceipt,
26
27
  } from '@wagmi/core';
@@ -93,17 +94,26 @@ import {
93
94
  PointsIncentive,
94
95
  type PointsIncentivePayload,
95
96
  } from './Incentives/PointsIncentive';
97
+ import {
98
+ LimitedSignerValidator,
99
+ type LimitedSignerValidatorPayload,
100
+ } from './Validators/LimitedSignerValidator';
96
101
  import {
97
102
  SignerValidator,
98
103
  type SignerValidatorPayload,
99
104
  } from './Validators/SignerValidator';
100
- import { type Validator, validatorFromAddress } from './Validators/Validator';
105
+ import {
106
+ BoostValidatorEOA,
107
+ type Validator,
108
+ validatorFromAddress,
109
+ } from './Validators/Validator';
101
110
  import {
102
111
  BoostCoreNoIdentifierEmitted,
103
112
  BoostNotFoundError,
104
113
  BudgetMustAuthorizeBoostCore,
105
114
  DeployableUnknownOwnerProvidedError,
106
115
  IncentiveNotCloneableError,
116
+ InvalidProtocolChainIdError,
107
117
  MustInitializeBudgetError,
108
118
  } from './errors';
109
119
  import {
@@ -347,8 +357,6 @@ export class BoostCore extends Deployable<
347
357
  options,
348
358
  );
349
359
 
350
- console.log(onChainPayload);
351
-
352
360
  const boostHash = await boostFactory(options.config, {
353
361
  ...this.optionallyAttachAccount(options.account),
354
362
  // biome-ignore lint/suspicious/noExplicitAny: Accept any shape of valid wagmi/viem parameters, wagmi does the same thing internally
@@ -441,9 +449,24 @@ export class BoostCore extends Deployable<
441
449
  }
442
450
  }
443
451
 
452
+ // If not providing a custom validator, use either Boost's mainnet or testnet EOA, depending on provided chain id and given chain configurations
444
453
  if (!payload.validator) {
454
+ const chains = getChains(options.config).filter(
455
+ (chain) => !!this.addresses[chain.id] && chain.id === chainId,
456
+ );
457
+ const chain = chains.at(0);
458
+ if (!chain)
459
+ throw new InvalidProtocolChainIdError(
460
+ chainId,
461
+ Object.keys(this.addresses).map(Number),
462
+ );
463
+ const testnet = chain.testnet || chain.id === 31337;
445
464
  payload.validator = this.SignerValidator({
446
- signers: [payload.owner],
465
+ signers: [
466
+ (testnet
467
+ ? BoostValidatorEOA.TESTNET
468
+ : BoostValidatorEOA.MAINNET) as unknown as Address,
469
+ ],
447
470
  validatorCaller: coreAddress,
448
471
  });
449
472
  }
@@ -800,7 +823,7 @@ export class BoostCore extends Deployable<
800
823
  budget,
801
824
  validator,
802
825
  allowList,
803
- incentives,
826
+ incentives: incentives as Incentive[],
804
827
  protocolFee,
805
828
  maxParticipants,
806
829
  owner,
@@ -1372,6 +1395,29 @@ export class BoostCore extends Deployable<
1372
1395
  );
1373
1396
  }
1374
1397
 
1398
+ /**
1399
+ * Bound {@link LimitedSignerValidator} constructor that reuses the same configuration as the Boost Core instance.
1400
+ *
1401
+ * @example
1402
+ * ```ts
1403
+ * const validator = core.LimitedSignerValidator({ ... }) // is roughly equivalent to
1404
+ * const validator = new LimitedSignerValidator({ config: core._config, account: core._account }, { ... })
1405
+ * ```
1406
+ * @param {DeployablePayloadOrAddress<LimitedSignerValidatorPayload>} options
1407
+ * @param {?boolean} [isBase]
1408
+ * @returns {LimitedSignerValidator}
1409
+ */
1410
+ LimitedSignerValidator(
1411
+ options: DeployablePayloadOrAddress<LimitedSignerValidatorPayload>,
1412
+ isBase?: boolean,
1413
+ ) {
1414
+ return new LimitedSignerValidator(
1415
+ { config: this._config, account: this._account },
1416
+ options,
1417
+ isBase,
1418
+ );
1419
+ }
1420
+
1375
1421
  /**
1376
1422
  * Bound {@link ERC20VariableCriteriaIncentive} constructor that reuses the same configuration as the Boost Core instance.
1377
1423
  *
@@ -1,15 +1,15 @@
1
- import { loadFixture } from '@nomicfoundation/hardhat-network-helpers';
2
- import { isAddress, pad, parseEther, zeroAddress } from 'viem';
3
- import { beforeAll, describe, expect, test } from 'vitest';
4
- import { accounts } from '@boostxyz/test/accounts';
1
+ import { loadFixture } from "@nomicfoundation/hardhat-network-helpers";
2
+ import { isAddress, pad, parseEther, zeroAddress } from "viem";
3
+ import { beforeAll, describe, expect, test } from "vitest";
4
+ import { accounts } from "@boostxyz/test/accounts";
5
5
  import {
6
6
  type Fixtures,
7
7
  defaultOptions,
8
8
  deployFixtures,
9
9
  freshBoost,
10
- } from '@boostxyz/test/helpers';
11
- import { PointsIncentive } from './PointsIncentive';
12
- import { Roles } from '../Deployable/DeployableTargetWithRBAC';
10
+ } from "@boostxyz/test/helpers";
11
+ import { PointsIncentive } from "./PointsIncentive";
12
+ import { Roles } from "../Deployable/DeployableTargetWithRBAC";
13
13
 
14
14
  let fixtures: Fixtures;
15
15
 
@@ -25,15 +25,15 @@ function freshAllowList(fixtures: Fixtures) {
25
25
  };
26
26
  }
27
27
 
28
- describe('AllowListIncentive', () => {
28
+ describe("AllowListIncentive", () => {
29
29
  beforeAll(async () => {
30
30
  fixtures = await loadFixture(deployFixtures(defaultOptions));
31
31
  });
32
32
 
33
- test('can successfully be deployed', async () => {
33
+ test("can successfully be deployed", async () => {
34
34
  const action = new PointsIncentive(defaultOptions, {
35
35
  venue: zeroAddress,
36
- selector: '0xdeadb33f',
36
+ selector: "0xdeadb33f",
37
37
  reward: 1n,
38
38
  limit: 1n,
39
39
  });
@@ -41,7 +41,7 @@ describe('AllowListIncentive', () => {
41
41
  expect(isAddress(action.assertValidAddress())).toBe(true);
42
42
  });
43
43
 
44
- test('can claim', async () => {
44
+ test("can claim", async () => {
45
45
  // biome-ignore lint/style/noNonNullAssertion: we know this is defined
46
46
  const referrer = accounts.at(1)?.account!;
47
47
  // biome-ignore lint/style/noNonNullAssertion: we know this is defined
@@ -63,15 +63,14 @@ describe('AllowListIncentive', () => {
63
63
  );
64
64
 
65
65
  const claimant = trustedSigner.account;
66
- const incentiveData = pad('0xdef456232173821931823712381232131391321934');
66
+ const incentiveData = pad("0xdef456232173821931823712381232131391321934");
67
67
  console.log(claimant);
68
68
 
69
- const incentiveQuantity = 1;
70
69
  const claimDataPayload = await boost.validator.encodeClaimData({
71
70
  signer: trustedSigner,
72
71
  incentiveData,
73
72
  chainId: defaultOptions.config.chains[0].id,
74
- incentiveQuantity,
73
+ incentiveQuantity: boost.incentives.length,
75
74
  claimant,
76
75
  boostId: boost.id,
77
76
  });
@@ -82,12 +81,12 @@ describe('AllowListIncentive', () => {
82
81
  0n,
83
82
  referrer,
84
83
  claimDataPayload,
85
- { value: parseEther('0.000075'), account: trustedSigner.privateKey },
84
+ { value: parseEther("0.000075"), account: trustedSigner.privateKey },
86
85
  );
87
86
  expect(await allowList.isAllowed(trustedSigner.account)).toBe(true);
88
87
  });
89
88
 
90
- test('cannot claim twice', async () => {
89
+ test("cannot claim twice", async () => {
91
90
  // biome-ignore lint/style/noNonNullAssertion: we know this is defined
92
91
  const referrer = accounts.at(1)?.account!;
93
92
  // biome-ignore lint/style/noNonNullAssertion: we know this is defined
@@ -107,16 +106,15 @@ describe('AllowListIncentive', () => {
107
106
  [allowListIncentive.assertValidAddress()],
108
107
  [Roles.MANAGER],
109
108
  );
110
- const incentiveQuantity = 1;
111
109
  const claimant = trustedSigner.account;
112
- const incentiveData = pad('0xdef456232173821931823712381232131391321934');
110
+ const incentiveData = pad("0xdef456232173821931823712381232131391321934");
113
111
  console.log(claimant);
114
112
 
115
113
  const claimDataPayload = await boost.validator.encodeClaimData({
116
114
  signer: trustedSigner,
117
115
  incentiveData,
118
116
  chainId: defaultOptions.config.chains[0].id,
119
- incentiveQuantity,
117
+ incentiveQuantity: boost.incentives.length,
120
118
  claimant,
121
119
  boostId: boost.id,
122
120
  });
@@ -126,7 +124,7 @@ describe('AllowListIncentive', () => {
126
124
  0n,
127
125
  referrer,
128
126
  claimDataPayload,
129
- { value: parseEther('0.000075'), account: trustedSigner.privateKey },
127
+ { value: parseEther("0.000075"), account: trustedSigner.privateKey },
130
128
  );
131
129
  try {
132
130
  await fixtures.core.claimIncentive(
@@ -134,7 +132,7 @@ describe('AllowListIncentive', () => {
134
132
  0n,
135
133
  referrer,
136
134
  claimDataPayload,
137
- { value: parseEther('0.000075'), account: trustedSigner.privateKey },
135
+ { value: parseEther("0.000075"), account: trustedSigner.privateKey },
138
136
  );
139
137
  } catch (e) {
140
138
  expect(e).toBeInstanceOf(Error);
@@ -1,8 +1,8 @@
1
- import { readMockErc20BalanceOf } from '@boostxyz/evm';
2
- import { loadFixture } from '@nomicfoundation/hardhat-network-helpers';
3
- import { isAddress, pad, parseEther, zeroAddress } from 'viem';
4
- import { beforeAll, beforeEach, describe, expect, test } from 'vitest';
5
- import { accounts } from '@boostxyz/test/accounts';
1
+ import { readMockErc20BalanceOf } from "@boostxyz/evm";
2
+ import { loadFixture } from "@nomicfoundation/hardhat-network-helpers";
3
+ import { isAddress, pad, parseEther, zeroAddress } from "viem";
4
+ import { beforeAll, beforeEach, describe, expect, test } from "vitest";
5
+ import { accounts } from "@boostxyz/test/accounts";
6
6
  import {
7
7
  type BudgetFixtures,
8
8
  type Fixtures,
@@ -10,12 +10,12 @@ import {
10
10
  deployFixtures,
11
11
  freshBoost,
12
12
  fundBudget,
13
- } from '@boostxyz/test/helpers';
14
- import { CGDAIncentive } from './CGDAIncentive';
13
+ } from "@boostxyz/test/helpers";
14
+ import { CGDAIncentive } from "./CGDAIncentive";
15
15
 
16
16
  let fixtures: Fixtures, budgets: BudgetFixtures;
17
17
 
18
- describe('CGDAIncentive', () => {
18
+ describe("CGDAIncentive", () => {
19
19
  beforeAll(async () => {
20
20
  fixtures = await loadFixture(deployFixtures(defaultOptions));
21
21
  });
@@ -24,20 +24,20 @@ describe('CGDAIncentive', () => {
24
24
  budgets = await loadFixture(fundBudget(defaultOptions, fixtures));
25
25
  });
26
26
 
27
- test('can successfully be deployed', async () => {
27
+ test("can successfully be deployed", async () => {
28
28
  const action = new CGDAIncentive(defaultOptions, {
29
29
  asset: budgets.erc20.assertValidAddress(),
30
30
  initialReward: 1n,
31
31
  totalBudget: 10n,
32
32
  rewardBoost: 1n,
33
33
  rewardDecay: 1n,
34
- manager: budgets.budget.address || zeroAddress
34
+ manager: budgets.budget.address || zeroAddress,
35
35
  });
36
36
  await action.deploy();
37
37
  expect(isAddress(action.assertValidAddress())).toBe(true);
38
38
  });
39
39
 
40
- test('can claim', async () => {
40
+ test("can claim", async () => {
41
41
  // biome-ignore lint/style/noNonNullAssertion: we know this is defined
42
42
  const referrer = accounts.at(1)!.account!;
43
43
  // biome-ignore lint/style/noNonNullAssertion: we know this is defined
@@ -56,14 +56,13 @@ describe('CGDAIncentive', () => {
56
56
  });
57
57
 
58
58
  const claimant = trustedSigner.account;
59
- const incentiveData = pad('0xdef456232173821931823712381232131391321934');
59
+ const incentiveData = pad("0xdef456232173821931823712381232131391321934");
60
60
 
61
- const incentiveQuantity = 1;
62
61
  const claimDataPayload = await boost.validator.encodeClaimData({
63
62
  signer: trustedSigner,
64
63
  incentiveData,
65
64
  chainId: defaultOptions.config.chains[0].id,
66
- incentiveQuantity,
65
+ incentiveQuantity: boost.incentives.length,
67
66
  claimant,
68
67
  boostId: boost.id,
69
68
  });
@@ -73,7 +72,7 @@ describe('CGDAIncentive', () => {
73
72
  0n,
74
73
  referrer,
75
74
  claimDataPayload,
76
- { value: parseEther('0.000075') },
75
+ { value: parseEther("0.000075") },
77
76
  );
78
77
  expect(
79
78
  await readMockErc20BalanceOf(defaultOptions.config, {
@@ -83,7 +82,7 @@ describe('CGDAIncentive', () => {
83
82
  ).toBe(1n);
84
83
  });
85
84
 
86
- test('cannot claim twice', async () => {
85
+ test("cannot claim twice", async () => {
87
86
  // biome-ignore lint/style/noNonNullAssertion: we know this is defined
88
87
  const referrer = accounts.at(1)!.account!;
89
88
  // biome-ignore lint/style/noNonNullAssertion: we know this is defined
@@ -94,7 +93,7 @@ describe('CGDAIncentive', () => {
94
93
  totalBudget: 10n,
95
94
  rewardBoost: 1n,
96
95
  rewardDecay: 1n,
97
- manager: budgets.budget.address || zeroAddress
96
+ manager: budgets.budget.address || zeroAddress,
98
97
  });
99
98
  const boost = await freshBoost(fixtures, {
100
99
  budget: budgets.budget,
@@ -102,13 +101,12 @@ describe('CGDAIncentive', () => {
102
101
  });
103
102
 
104
103
  const claimant = trustedSigner.account;
105
- const incentiveData = pad('0xdef456232173821931823712381232131391321934');
106
- const incentiveQuantity = 1;
104
+ const incentiveData = pad("0xdef456232173821931823712381232131391321934");
107
105
  const claimDataPayload = await boost.validator.encodeClaimData({
108
106
  signer: trustedSigner,
109
107
  incentiveData,
110
108
  chainId: defaultOptions.config.chains[0].id,
111
- incentiveQuantity,
109
+ incentiveQuantity: boost.incentives.length,
112
110
  claimant,
113
111
  boostId: boost.id,
114
112
  });
@@ -118,7 +116,7 @@ describe('CGDAIncentive', () => {
118
116
  0n,
119
117
  referrer,
120
118
  claimDataPayload,
121
- { value: parseEther('0.000075') },
119
+ { value: parseEther("0.000075") },
122
120
  );
123
121
  try {
124
122
  await fixtures.core.claimIncentive(
@@ -126,7 +124,7 @@ describe('CGDAIncentive', () => {
126
124
  0n,
127
125
  referrer,
128
126
  claimDataPayload,
129
- { value: parseEther('0.000075') },
127
+ { value: parseEther("0.000075") },
130
128
  );
131
129
  } catch (e) {
132
130
  expect(e).toBeInstanceOf(Error);
@@ -1,8 +1,8 @@
1
- import { readMockErc1155BalanceOf } from '@boostxyz/evm';
2
- import { loadFixture } from '@nomicfoundation/hardhat-network-helpers';
3
- import { isAddress, pad, parseEther, zeroAddress, zeroHash } from 'viem';
4
- import { beforeAll, beforeEach, describe, expect, test } from 'vitest';
5
- import { accounts } from '@boostxyz/test/accounts';
1
+ import { readMockErc1155BalanceOf } from "@boostxyz/evm";
2
+ import { loadFixture } from "@nomicfoundation/hardhat-network-helpers";
3
+ import { isAddress, pad, parseEther, zeroAddress, zeroHash } from "viem";
4
+ import { beforeAll, beforeEach, describe, expect, test } from "vitest";
5
+ import { accounts } from "@boostxyz/test/accounts";
6
6
  import {
7
7
  type BudgetFixtures,
8
8
  type Fixtures,
@@ -10,14 +10,14 @@ import {
10
10
  deployFixtures,
11
11
  freshBoost,
12
12
  fundBudget,
13
- } from '@boostxyz/test/helpers';
14
- import { ERC1155Incentive, ERC1155StrategyType } from './ERC1155Incentive';
13
+ } from "@boostxyz/test/helpers";
14
+ import { ERC1155Incentive, ERC1155StrategyType } from "./ERC1155Incentive";
15
15
 
16
- const BOOST_CORE_CLAIM_FEE = parseEther('0.000075');
16
+ const BOOST_CORE_CLAIM_FEE = parseEther("0.000075");
17
17
 
18
18
  let fixtures: Fixtures, budgets: BudgetFixtures;
19
19
 
20
- describe.skip('ERC1155Incentive', () => {
20
+ describe.skip("ERC1155Incentive", () => {
21
21
  beforeAll(async () => {
22
22
  fixtures = await loadFixture(deployFixtures(defaultOptions));
23
23
  });
@@ -26,19 +26,19 @@ describe.skip('ERC1155Incentive', () => {
26
26
  budgets = await loadFixture(fundBudget(defaultOptions, fixtures));
27
27
  });
28
28
 
29
- test('can successfully be deployed', async () => {
29
+ test("can successfully be deployed", async () => {
30
30
  const action = new ERC1155Incentive(defaultOptions, {
31
31
  asset: zeroAddress,
32
32
  strategy: ERC1155StrategyType.MINT,
33
33
  tokenId: 0n,
34
34
  limit: 10n,
35
- extraData: '0x',
35
+ extraData: "0x",
36
36
  });
37
37
  await action.deploy();
38
38
  expect(isAddress(action.assertValidAddress())).toBe(true);
39
39
  });
40
40
 
41
- test('can claim', async () => {
41
+ test("can claim", async () => {
42
42
  // biome-ignore lint/style/noNonNullAssertion: we know this is defined
43
43
  const referrer = accounts.at(1)!.account!,
44
44
  // biome-ignore lint/style/noNonNullAssertion: we know this is defined
@@ -59,13 +59,12 @@ describe.skip('ERC1155Incentive', () => {
59
59
  });
60
60
 
61
61
  const claimant = trustedSigner.account;
62
- const incentiveData = pad('0xdef456232173821931823712381232131391321934');
63
- const incentiveQuantity = 1;
62
+ const incentiveData = pad("0xdef456232173821931823712381232131391321934");
64
63
  const claimDataPayload = await boost.validator.encodeClaimData({
65
64
  signer: trustedSigner,
66
65
  incentiveData,
67
66
  chainId: defaultOptions.config.chains[0].id,
68
- incentiveQuantity,
67
+ incentiveQuantity: boost.incentives.length,
69
68
  claimant,
70
69
  boostId: boost.id,
71
70
  });